﻿using System.Collections.ObjectModel;
using System.Windows.Input;
using Peter.Common;
using Peter.Sdw.Data;

namespace Peter.Sdw.Logic
{
   /// <summary>
   /// View model for style input.
   /// </summary>
   public class StyleModel : ViewModelBase
   {
      private bool m_CanSpan;
      private string m_EndStyle;
      private string m_StartStyle;
      private bool m_SpansMulitiple;
      private Style m_SelectedStyle;
      private RelayCommand m_CmdStyle;
      private RelayCommand m_CmdSetStyle;
      private readonly ObservableCollection <Style> m_Styles;

      /// <summary>
      /// Initializes a new style model.
      /// </summary>
      /// <param name="styleable">The styleable parent.</param>
      public StyleModel (IStyleable styleable)
      {
         this.Parent = styleable;
         this.m_Styles = new ObservableCollection <Style> ();
      }

      /// <summary>
      /// Gets the parent item.
      /// </summary>
      public IStyleable Parent { get; private set; }

      /// <summary>
      /// Gets the list of styles.
      /// </summary>
      public ObservableCollection<Style> Styles { get { return this.m_Styles; } }

      /// <summary>
      /// Gets or Sets the start style.
      /// </summary>
      public string StartStyle
      {
         get { return this.m_StartStyle; }
         set
         {
            this.m_StartStyle = value;
            this.RaisePropertyChanged("StartStyle");
         }
      }

      /// <summary>
      /// Gets or Sets the end style.
      /// </summary>
      public string EndStyle
      {
         get { return this.m_EndStyle; }
         set
         {
            this.m_EndStyle = value;
            this.RaisePropertyChanged ("EndStyle");
         }
      }

      /// <summary>
      /// Gets or Sets the selected style.
      /// </summary>
      public Style SelectedStyle
      {
         get { return this.m_SelectedStyle; }
         set
         {
            this.m_SelectedStyle = value;
            this.RaisePropertyChanged ("SelectedStyle");
            if (this.m_SelectedStyle == null) return;
            this.EndStyle = this.SelectedStyle.End;
            this.StartStyle = this.SelectedStyle.Start;
            this.Parent.EndIndex = this.SelectedStyle.EndIndex;
            this.Parent.StartIndex = this.SelectedStyle.StartIndex;
            this.SpansMulitiple = this.SelectedStyle.SpansMultiple;
         }
      }

      /// <summary>
      /// Gets or Sets if this item can span multiple entries.
      /// </summary>
      public bool CanSpan
      {
         get { return this.m_CanSpan; }
         set
         {
            this.m_CanSpan = value;
            this.RaisePropertyChanged ("CanSpan");
         }
      }

      /// <summary>
      /// Gets or Sets if the style spans mulitple entries.
      /// </summary>
      public bool SpansMulitiple
      {
         get { return this.m_SpansMulitiple; }
         set
         {
            this.m_SpansMulitiple = value;
            this.RaisePropertyChanged ("SpansMulitiple");
         }
      }

      /// <summary>
      /// Gets the command to set the style.
      /// </summary>
      public ICommand SetStyleCommand
      {
         get { return this.m_CmdSetStyle ?? (this.m_CmdSetStyle = new RelayCommand (this.OnSetStyle)); }
      }

      /// <summary>
      /// Gets the command to set the style.
      /// </summary>
      public ICommand StyleCommand
      {
         get { return this.m_CmdStyle ?? (this.m_CmdStyle = new RelayCommand (this.OnStyle, this.CanStyle)); }
      }

      /// <summary>
      /// Checks to see if we can add/delete/edit a style.
      /// </summary>
      /// <param name="obj">Command parameter.</param>
      /// <returns>True if command can execute, otherwise false.</returns>
      private bool CanStyle (object obj)
      {
         var action = obj.ToString ().ToLower ();
         if (action == "add") {
            if (!this.SpansMulitiple)
               return !string.IsNullOrWhiteSpace (this.StartStyle) && !string.IsNullOrWhiteSpace (this.EndStyle);
            return !string.IsNullOrWhiteSpace (this.StartStyle) || !string.IsNullOrWhiteSpace (this.EndStyle);
         }
         return this.SelectedStyle != null;
      }

      /// <summary>
      /// Adds/deletes/edits a style.
      /// </summary>
      /// <param name="obj">Command parameter.</param>
      private void OnStyle (object obj)
      {
         var action = obj.ToString ().ToLower ();
         if (action == "add") {
            var style = new Style {
               End = this.EndStyle,
               Start = this.StartStyle,
               EndIndex = this.Parent.EndIndex,
               StartIndex = this.Parent.StartIndex,
               SpansMultiple = this.SpansMulitiple
            };
            this.Parent.AddStyle (style);
         } else if (action == "delete") {
            this.Parent.RemoveStyle (this.SelectedStyle);
         } else if (action == "edit") {
            this.SelectedStyle.End = this.EndStyle;
            this.SelectedStyle.Start = this.StartStyle;
            this.SelectedStyle.EndIndex = this.Parent.EndIndex;
            this.SelectedStyle.StartIndex = this.Parent.StartIndex;
            this.SelectedStyle.SpansMultiple = this.SpansMulitiple;
            this.Parent.EditStyle (this.SelectedStyle);
         }
      }

      private void OnSetStyle (object obj)
      {
         var style = obj.ToString ().ToLower ();
         switch (style) {
            case "calign":
               this.StartStyle = "<div class=\"tCenter\">";
               this.EndStyle = "</div>";
               break;
            case "ralign":
               this.StartStyle = "<div class=\"tRight\">";
               this.EndStyle = "</div>";
               break;
            case "title":
               this.StartStyle = "<h5 class=\"text-center\" style=\"font-weight:bold;\">";
               this.EndStyle = "</h5>";
               break;
            case "subtitle":
               this.StartStyle = "<div class=\"text-center\" style=\"font-weight:bold;font-style:italic;\">";
               this.EndStyle = "</div>";
               break;
            case "summary":
               this.StartStyle = "<div class=\"text-center\" style=\"font-size:smaller;margin:0.825rem\">";
               this.EndStyle = "</div>";
               break;
            default:
               this.StartStyle = "<" + style + ">";
               this.EndStyle = "</" + style + ">";
               break;
         }
      }
   }
}
